/*
 *
 * This file is part of the open-source SeetaFace engine, which includes three modules:
 * SeetaFace Detection, SeetaFace Alignment, and SeetaFace Identification.
 *
 * This file is part of the SeetaFace Detection module, containing codes implementing the
 * face detection method described in the following paper:
 *
 *
 *   Funnel-structured cascade for multi-view face detection with alignment awareness,
 *   Shuzhe Wu, Meina Kan, Zhenliang He, Shiguang Shan, Xilin Chen.
 *   In Neurocomputing (under review)
 *
 *
 * Copyright (C) 2016, Visual Information Processing and Learning (VIPL) group,
 * Institute of Computing Technology, Chinese Academy of Sciences, Beijing, China.
 *
 * The codes are mainly developed by Shuzhe Wu (a Ph.D supervised by Prof. Shiguang Shan)
 *
 * As an open-source face recognition engine: you can redistribute SeetaFace source codes
 * and/or modify it under the terms of the BSD 2-Clause License.
 *
 * You should have received a copy of the BSD 2-Clause License along with the software.
 * If not, see < https://opensource.org/licenses/BSD-2-Clause>.
 *
 * Contact Info: you can send an email to SeetaFace@vipl.ict.ac.cn for any problems.
 *
 * Note: the above information must be kept whenever or wherever the codes are used.
 *
 */

#include "surf_mlp.h"

#include <string.h>
//using namespace std;

void InitSURFMLP(struct classSURFMLP *p)
{
	//Classifier();
	//p->model_(MLP())
	//InitMLP(&p->mlp);
}

void SURFMLPSetFeatureMap(struct classSURFMLP *p, SURFFeatureMap* feat_map) {
	p->feat_map_ = *feat_map;
}

int SURFMLPtype(struct classSURFMLP *p) {
	return SURF_MLP;
}
void SURFMLPSetThreshold(struct classSURFMLP *p, float thresh) { p->thresh_ = thresh; }

bool SURFMLPClassify(struct classSURFMLP *p, SURFFeatureMap* feat_map, FDHandle* handle, float* score, float* outputs) {
	
  float* dest = p->input_buf_;
  int len_featid = malloc_usable_size(p->feat_id_) / sizeof(p->feat_id_[0]) - 1;
  int i;
 // printf("len_featid=%d\n",len_featid);
  for ( i = 0; i < len_featid; i++) {
	  SURFFeatureMapGetFeatureVector(feat_map, p->feat_id_[i] - 1, dest);
	  dest += SURFFeatureMapGetFeatureVectorDim(feat_map, p->feat_id_[i]);
  }
  
  int outputLen = MLPGetOutputDim(&p->mlp);
  //p->output_buf_ = (float*)malloc(sizeof(float)*outputLen);
  p->output_buf_ = (float*)(handle->mem + handle->MemeryUsed);
  handle->MemeryUsed += sizeof(float)*256;
  memset(p->output_buf_, 0, sizeof(float)* 256);
  
  MLPCompute(&p->mlp,p->input_buf_, p->output_buf_);
  
  if (score != NULL)
    *score = p->output_buf_[0];
  if (outputs != NULL) {
    memcpy(outputs, p->output_buf_,
		MLPGetOutputDim(&p->mlp) * sizeof(float));
  }
  
  return (p->output_buf_[0] > p->thresh_);
  
 // return false;
}

void SURFMLPAddFeatureByID(struct classSURFMLP *p, int32_t feat_id,int n) {
  //p->feat_id_.push_back(feat_id);

	p->feat_id_[n] = feat_id;
}

void SURFMLPAddLayer(struct classSURFMLP *p, int32_t input_dim, int32_t output_dim,
    const float* weights, const float* bias, int list,bool is_output) {
	if ( list == 1  )//MLPGetLayerNum(&p->mlp) == 0)
		// p->input_buf_.resize(input_dim);
	{
		p->input_buf_ = (float*)malloc(sizeof(float)*input_dim);
		memset(p->input_buf_, 0, sizeof(float)*input_dim);
	}
		
  MLPAddLayer(&p->mlp,input_dim, output_dim, weights, bias, list, is_output);
}

